﻿namespace CommonData.Entity
{
    using CommonData.Model.Core;
    using System;
    using System.Linq;
    using System.Reflection;

    public class BaseEntityHelper : BaseEntityAbstract
    {
        private const int LENGTH = 1;

        public override ColumnAttribute[] GetColumnAttribute<T>() 
        {
            return this.GetTableInfo<T>().Columns;
        }

        public override ColumnAttribute[] GetColumnAttribute(IEntity entity)
        {
            return this.GetTableInfo(entity).Columns;
        }

        public override ColumnAttribute[] GetColumnAttribute(Type type)
        {
            return this.GetTableInfo(type).Columns;
        }

        public override FieldInfo[] GetFieldInfo<T>() 
        {
            return this.GetTableInfo<T>().Fields;
        }

        public override FieldInfo[] GetFieldInfo(IEntity entity)
        {
            return this.GetTableInfo(entity).Fields;
        }

        public override FieldInfo[] GetFieldInfo(Type type)
        {
            return this.GetTableInfo(type).Fields;
        }

        public override LinkTableAttribute[] GetLinkTableAttribute<T>() 
        {
            return this.GetTableInfo<T>().LinkTable;
        }

        public override LinkTableAttribute[] GetLinkTableAttribute(IEntity entity)
        {
            return this.GetTableInfo(entity).LinkTable;
        }

        public override LinkTableAttribute[] GetLinkTableAttribute(Type type)
        {
            return this.GetTableInfo(type).LinkTable;
        }

        public override LinkTablesAttribute[] GetLinkTablesAttribute<T>() 
        {
            return this.GetTableInfo<T>().LinkTables;
        }

        public override LinkTablesAttribute[] GetLinkTablesAttribute(IEntity entity)
        {
            return this.GetTableInfo(entity).LinkTables;
        }

        public override LinkTablesAttribute[] GetLinkTablesAttribute(Type type)
        {
            return this.GetTableInfo(type).LinkTables;
        }

        public override PropertyInfo[] GetPropertyInfo<T>() 
        {
            return this.GetTableInfo<T>().Properties;
        }

        public override PropertyInfo[] GetPropertyInfo(IEntity entity)
        {
            return this.GetTableInfo(entity).Properties;
        }

        public override PropertyInfo[] GetPropertyInfo(Type type)
        {
            return this.GetTableInfo(type).Properties;
        }

        public override TableInfo GetTableInfo<T>() 
        {
            Type type = typeof(T);
            return this.GetTableInfo(type);
        }

        public override TableInfo GetTableInfo(IEntity entity)
        {
            return this.GetTableInfo(entity.GetType());
        }

        public override TableInfo GetTableInfo(Type type)
        {
            TableInfo tableInfo = EntityTypeCache.GetTableInfo(type);
            if (tableInfo == null)
            {
                tableInfo = new TableInfo();
                TableAttribute[] customAttributes = type.GetCustomAttributes(typeof(TableAttribute), false) as TableAttribute[];
                PropertyInfo[] properties = type.GetProperties();
                foreach (PropertyInfo info2 in properties)
                {
                    tableInfo.DicProperties.Add(info2.Name, info2);
                    if (info2.GetCustomAttributes(typeof(ColumnAttribute), false).Length == 1)
                    {
                        tableInfo.DicColumns.Add(info2.Name, info2.GetCustomAttributes(typeof(ColumnAttribute), false)[0] as ColumnAttribute);
                    }
                    if (info2.GetCustomAttributes(typeof(LinkTableAttribute), false).Length == 1)
                    {
                        tableInfo.DicLinkTable.Add(info2.Name, info2.GetCustomAttributes(typeof(LinkTableAttribute), false)[0] as LinkTableAttribute);
                    }
                    if (info2.GetCustomAttributes(typeof(LinkTablesAttribute), false).Length == 1)
                    {
                        tableInfo.DicLinkTables.Add(info2.Name, info2.GetCustomAttributes(typeof(LinkTablesAttribute), false)[0] as LinkTablesAttribute);
                    }
                }
                FieldInfo[] fields = type.GetFields();
                foreach (FieldInfo info3 in fields)
                {
                    tableInfo.DicFields.Add(info3.Name, info3);
                }
                if (customAttributes.Length != 1)
                {
                    throw new Exception("一个实体类上不能有相同的特性");
                }
                tableInfo.Table = customAttributes[0];
                tableInfo.Columns = tableInfo.DicColumns.Values.ToArray<ColumnAttribute>();
                tableInfo.Fields = tableInfo.DicFields.Values.ToArray<FieldInfo>();
                tableInfo.LinkTable = tableInfo.DicLinkTable.Values.ToArray<LinkTableAttribute>();
                tableInfo.LinkTables = tableInfo.DicLinkTables.Values.ToArray<LinkTablesAttribute>();
                tableInfo.Properties = tableInfo.DicProperties.Values.ToArray<PropertyInfo>();
                EntityTypeCache.InsertTableInfo(type, tableInfo);
            }
            return tableInfo;
        }
    }
}

